package com.imooc.pan.server.common.listener.file;

import com.alibaba.fastjson.JSON;
import com.imooc.pan.core.constants.RPanConstants;
import com.imooc.pan.core.exception.RPanBusinessException;
import com.imooc.pan.server.common.event.file.FilePhysicalDeleteEvent;
import com.imooc.pan.server.common.event.log.ErrorLogEvent;
import com.imooc.pan.server.modules.file.entity.RPanFile;
import com.imooc.pan.server.modules.file.entity.RPanUserFile;
import com.imooc.pan.server.modules.file.enums.FolderFlagEnum;
import com.imooc.pan.server.modules.file.service.RPanFileService;
import com.imooc.pan.server.modules.file.service.RPanUserFileService;
import com.imooc.pan.storage.engine.core.StorageEngine;
import com.imooc.pan.storage.engine.core.context.DeleteFileContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.lang.management.ClassLoadingMXBean;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 文件物理删除监听器
 * @author hhb
 * @data 2024/6/16 20:09
 */
@Component
public class FilePhysicalDeleteEventListener implements ApplicationContextAware {

    @Autowired
    private RPanFileService rPanFileService;

    @Autowired
    private RPanUserFileService rPanUserFileService;

    @Autowired
    private StorageEngine storageEngine;

    private ApplicationContext applicationContext;


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 清除物理文件记录
     * @param event
     */
    @EventListener(FilePhysicalDeleteEvent.class)
    public void physicalDelete(FilePhysicalDeleteEvent event){
        List<RPanUserFile> allRecords = event.getAllRecords();
        //获取真实文件id
        List<Long> realFileIdList = allRecords.stream()
                .filter(item-> Objects.equals(item.getFolderFlag(), FolderFlagEnum.NO.getCode()))
                .filter(this::isUnused)
                .map(RPanUserFile::getRealFileId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(realFileIdList)){
            return;
        }
        List<RPanFile> list = rPanFileService.lambdaQuery().in(RPanFile::getFileId, realFileIdList).list();
        List<String> realPath = list.stream().map(RPanFile::getRealPath).collect(Collectors.toList());
        if(!rPanFileService.removeByIds(realFileIdList)){
            applicationContext.publishEvent(new ErrorLogEvent(this,"实体文件记录" + JSON.toJSONString(realFileIdList)+ "数据库清除文件失败,请手动进行清除",RPanConstants.ZERO_LONG));
            return;
        }
        DeleteFileContext context = new DeleteFileContext();
        context.setRealPathList(realPath);
        try {
            //存储引擎清除文件
            storageEngine.delete(context);
        } catch (IOException e) {
            e.printStackTrace();
            applicationContext.publishEvent(new ErrorLogEvent(this,"实体文件" + JSON.toJSONString(realPath)+ "存储引擎清除文件失败,请手动进行清除",RPanConstants.ZERO_LONG));
        }

    }


    private boolean isUnused(RPanUserFile rPanUserFile) {
        return rPanUserFileService.lambdaQuery().eq(RPanUserFile::getRealFileId,rPanUserFile.getRealFileId()).count() == RPanConstants.ZERO_INT.intValue();
    }


}
